﻿//----------------------------------------------
//            NGUI: Next-Gen UI kit
// Copyright © 2011-2012 Tasharen Entertainment
//----------------------------------------------

using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// This is a script used to keep the game object scaled to 2/(Screen.height).
/// If you use it, be sure to NOT use UIOrthoCamera at the same time.
/// 
/// 这是一个脚本，用于保持游戏对象缩放到2/Screen.Height.
/// 如果你使用它，请务必在同样的时间不适用UIOrthoCamera.
/// </summary>

/*
 * ExecuteInEditMode 使一个脚本在编辑模式下运行，默认情况下脚本只有在运行模式下执行。
 * 通过添加这个属性，每一个脚本实力将总是有它的Update, FixedUpdate, 和 OnGUI方法每一帧执行当编辑器运行的时候。
 * 
 * AddComponentMenu 添加组件菜单。
 * 允许你在"Component"菜单中放置一个无论在哪的脚本，而不是仅仅在"Component->Scripts"菜单中。
 */
[ExecuteInEditMode]
[AddComponentMenu("NGUI/UI/Root")]
public class UIRoot : MonoBehaviour
{
    /// <summary>
    /// 声明一个静态的UIRoot对象集合。
    /// </summary>
	static List<UIRoot> mRoots = new List<UIRoot>();

    /// <summary>
    /// 自动的?
    /// </summary>
	public bool automatic = true;

    /// <summary>
    /// 手动高度?
    /// </summary>
	public int manualHeight = 800;

    /// <summary>
    /// 当前transform对象,在start初始化
    /// </summary>
	Transform mTrans;

    /// <summary>
    /// 脚本第一次执行，添加this对象到mRoot对象集合
    /// </summary>
	void Awake () { mRoots.Add(this); }
    /// <summary>
    /// 脚本销毁时，从mRoot集合中移除this对象
    /// </summary>
	void OnDestroy () { mRoots.Remove(this); }

	void Start ()
	{
        //初始化属性transfrom
		mTrans = transform;

        //获取子组件中的UI正交相机
		UIOrthoCamera oc = GetComponentInChildren<UIOrthoCamera>();
		
		if (oc != null)
		{
            /*
             * 在同一时间作为UIOrthoCamera，UIRoot不应该主动。禁用UIOrthoCamera
             * 从UIOrthoCamera正交相机获取当前Camera
             * 关闭Camera摄像机
             * 如果当前相机为null，设置正投影尺寸为1f.
             */
            Debug.LogWarning("UIRoot should not be active at the same time as UIOrthoCamera. Disabling UIOrthoCamera.", oc);
			Camera cam = oc.gameObject.GetComponent<Camera>();
			oc.enabled = false;
			if (cam != null) cam.orthographicSize = 1f;
		}
	}

	void Update ()
	{
        /*
         * Mathf.Max 返回两个或更多值中最大的值。
         * automatic自动开启true，去当前屏幕高度Screen.height，否则去手动高度manualHeight。
         * 设置高度.
         */
        manualHeight = Mathf.Max(2, automatic ? Screen.height : manualHeight);

        /*
         * size初始化为(当前屏幕)高度的一半.
         * localScale 相对于父级物体变换的缩放。
         * ls获取相对于父级的缩放
         */
        float size = 2f / manualHeight;
		Vector3 ls = mTrans.localScale;

        /*
         * Mathf.Approximately 比较两个浮点数值，看它们是否非常接近。
         */
        if (!Mathf.Approximately(ls.x, size) ||
			!Mathf.Approximately(ls.y, size) ||
			!Mathf.Approximately(ls.z, size))
		{
            //重新设置缩放
			mTrans.localScale = new Vector3(size, size, size);
		}
	}

	/// <summary>
	/// Broadcast the specified message to the entire UI.
    /// 广播整个UI指定的消息。
	/// </summary>

	static public void Broadcast (string funcName)
	{
		for (int i = 0, imax = mRoots.Count; i < imax; ++i)
		{
            /*
             * BroadcastMessage在游戏物体每一个MonoBehaviour和它的全部子物体上调用名为methodName的方法。
             * BroadcastMessage朝物体和所有子物体发送消息。对一个物体及其所有子物体，进行消息的广播，
             * 如果其中任何子物体上贴有脚本，而脚本中有相应的处理此消息的函数，则Invoke调用之。
             * 接受消息的此方法（函数）可以通过设置没有引用参数表来忽略传过来的消息中的参数。
             * 如果选项Option中设置成了SendMessageOptions.RequireReceiver，那么当没有任何脚本组件接受此消息时，
             * 一个相应的错误会弹出来。
             * 
             * SendMessageOptions.DontRequireReceiver 没有SendMessage所需的一个接收器。
             */
            UIRoot root = mRoots[i];
			if (root != null) root.BroadcastMessage(funcName, SendMessageOptions.DontRequireReceiver);
		}
	}

	/// <summary>
	/// Broadcast the specified message to the entire UI.
    /// 广播整个UI指定的消息,带参数
	/// </summary>

	static public void Broadcast (string funcName, object param)
	{
		if (param == null)
		{
            /*
             * SendMessage函数被窃听，当您尝试通过在参数字段中的“空”。它的行为，如果没有参数被指定。
             */
            // More on this: http://answers.unity3d.com/questions/55194/suggested-workaround-for-sendmessage-bug.html
			Debug.LogError("SendMessage is bugged when you try to pass 'null' in the parameter field. It behaves as if no parameter was specified.");
		}
		else
		{
			for (int i = 0, imax = mRoots.Count; i < imax; ++i)
			{
                /*
                 * 广播带指定方法名称和参数的消息
                 */
				UIRoot root = mRoots[i];
				if (root != null) root.BroadcastMessage(funcName, param, SendMessageOptions.DontRequireReceiver);
			}
		}
	}
}